package com.wolfeyes.common.utils.reflect.proxy.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;

//import org.apache.log4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import com.wolfeyes.domain.core.enums.common.DateFormatTypeEnum;
import com.wolfeyes.common.utils.datetime.DateUtilss;
import com.wolfeyes.common.utils.redis.RedisUtils;
import com.wolfeyes.common.utils.reflect.proxy.jdkproxy.simple.Person;

//import groovy.transform.stc.FirstParam.ThirdGenericType;

/**
 * 
 * @title 代理模式的英文叫做Proxy或Surrogate，中文都可译为”代理“，场景如下：
 * 1.代理类对象实例内部含有对被代理真实类对象实例的引用，从而可以在任何时候操作被代理真实类对象实例；
 * 2.代理类对象实例提供一个与被代理真实类对象实例相同的接口，以便可以在任何时候都可以替代被代理真实类对象实例
 *   控制对被代理真实类对象实例的引用，负责在需要的时候创建被代理真实类对象实例（和删除被代理真实类对象实例）；
 * 3.代理类对象实例通常在将客户端调用传递给被代理真实类对象实例之前或之后，都要执行某个操作，
 *   而不是单纯简单地将调用传递给被代理真实类对象实例。 <br/>
 * 处理者(Handler)
 * @description 指派动态代理中方法所要调用的调用处理程序invocationHandler
 * @author yanyl
 * @projectName bootdo
 * @className DynamicProxyHandler.java
 * @author yanyl
 * @email 1991yanyl@163.com
 * @date 2018-07-04 15:53:58
 * @since 2017年02月02日下午5:37:39
 * @createTime 2018年06月09日 下午17:04:13
 * @version 1.0.0
 *
 */
public class JDKDynamicProxyHandler implements InvocationHandler {

	/**
	 * slf4j日志对象
	 */
	private static final Logger logger = LoggerFactory.getLogger(JDKDynamicProxyHandler.class);
	// private Logger logger = Logger.getLogger(DynamicProxyHandler.class);

	/**
	 * 被代理的目标对象实例targetObject
	 */
	private Object targetObject;

	/**
	 * @title 快速获取被代理的目标对象实例targetObject的引用
	 * @see {@link Person #Person()}
	 * @description TODO(随机生成编号)
	 * @param arg 参数说明
	 * @param targetObject 被代理的目标对象实例
	 * @author yanyl
	 * @since 2018年07月12日上午11:37:39
	 * @return 返回类型 void
	 * @throws Exception
	 */
	public void setTarget(Object targetObject) {

		this.targetObject = targetObject;

	}

	/**
	 * @title 快速封装处理被代理的目标对象实例targetObject的方法调用并返回结果
	 * @see {@link Method}
	 * @description TODO(随机生成编号)
	 * @param arg 参数说明
	 * @param proxy 被代理的目标对象的代理类实例
	 * @param method 对应于在代理实例上调用接口方法的Method实例
	 * @param args 传入到代理实例上调用接口方法的参数值的对象数组
	 * @author yanyl
	 * @since 2018年07月12日上午11:37:39
	 * @return 返回类型 void
	 * @throws Exception
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		// 快速获取长格式的时间字符串；
		String startTime = DateUtilss.getTimeNow();
		
		// 打印控制台
		logger.info("执行开始时间:" + startTime);

		System.out.println("代理类：" + proxy.getClass());
		
		System.out.println("方法名称:" + method.getName());
		
		// 方法的参数值
		if(args != null && args.length > 0) {
			
			// 遍历(参数列表)参数值的对象数组
			for(int index = 0; index < args.length; index ++) {
				
				System.out.println("方法参数值：" + args[index]);
			}
		}
		
		// 在代理实例上处理方法调用并返回结果。
		Object result = method.invoke(this.targetObject, args);

		// 快速获取长格式的时间字符串；
		String endTime = DateUtilss.getTimeNow();
		
		// 打印到控制台
		logger.info("执行结束时间:" + endTime);

		// 返回method执行结果
		return result;

	}

}

